iT邦幫忙

2023 iThome 鐵人賽

DAY 3
0
Modern Web

Phoenix 1.7 完全教學系列 第 3

3 快速上手夠用的 Elixir (模組, 函式)

  • 分享至 

  • xImage
  •  

之所以說 Elixir 簡單,是因為比起物件導向,Elixir 只有 Function(函式) 沒有其他太抽象的隱藏概念,所有的組成都非常直覺。

定義 Module

定義 Module 使用 defmodule 關鍵字,並用 doend 來將內容包起來。 Module 名稱使用 camel case.

defmodule MyModule do
end

定義 Function

所有的 function 都必須要在模組底下定義

defmodule MyModule do
  def my_function do
    "Hello World"
  end
end

我們可以這樣呼叫

MyModule.my_function #=> "Hello World"

定義帶有參數的 Function

使用() 設定參數,並用 , 分隔

def add_them(first, second) do
  first + second
end

def add_them(first, second, third) do
  first + second + third
end

在 Elixir 裡面同一個模組可以有相同名字的函式,在稱呼這個函式的時候我們會一起寫上他的變數數量(arity),上面兩個函式分別是 add_them/2add_them/3,另外相同名字與相同 arity 的函式也是允許的,執行順序由上至下,這個在下個章節會說明。

執行 .ex 檔案

在上一篇我們都是使用 iex 來執行 Elixir 程式碼,但是在這邊要編輯並執行長一點的程式碼段落會很不方便,
我們可以使用編輯器並存成 .ex 檔案,通常會依照模組的名稱命名,如剛剛的範例可以叫:my_module.ex
接著可以在終端機執行 elixir my_module.ex 來執行它,

另外,在目前的章節,使用 iex 讀入該 module,再來執行會比較方便,
可以使用 iex my_module.ex 來開啟 iex 並執行該檔案內的程式碼
或是進入 iex 之後 使用 c("my_module.ex") 來讀取並執行

小測驗

寫一個匯率轉換小程式,他的執行結果如下
(這邊先不用考慮精準度與匯率,先寫個極簡單版本熟悉 Module 與 function 即可)

iex "ex_currency.ex"
ExCurrency.to_usd(300)
#=> 30
ExCurrency.to_jpy(300)
#=> 1200

參考解答

# ex_currency.ex
defmodule ExCurrency do
  def to_usd(twd) do
    div(twd, 30)
  end
  
  def to_jpy(twd) do
    twd * 4
  end
end

省略 Module

有幾個情況可以省略 module

  1. 呼叫同一個 Module 底下的另一個 function
defmodule ExCurrency do
  def to_jpy(twd) do
    twd * 4
  end
  
  def twd_2000_to_jpy() do
    to_jpy(2000) #=> 這邊前面可以省略 ExCurrency
  end
end
  1. 屬於 Kernel module 的 function 可以直接呼叫
is_atom(:hi) #=> true

Kernel 文件可以看所有的 Kernel 函式

  1. 有 import 該 module

拿剛剛的小測驗為例
使用 iex ex_currency.ex 進入 iex 後
再執行 import ExCurrency

我們就可以直接呼叫 to_jpy/1 function

匿名函式

使用 fn, ->end 定義匿名函式

to_jpy = fn twd -> twd * 4 end

多行的情況

to_jpy = fn twd ->
  # 很多行的複雜運算
  twd * 4
end

簡寫,省去變數名稱,在 &() 內由 &1 代表第一個變數,依此類推

to_jpy = &(&1 * 4)

直接執行匿名函式需要加一個 .
不過實際上比較少這樣執行

to_jpy.(300)
#=> 1200

通常會在 Enum.map/2Enum.reduce/3 等高階函式使用
(高階函式:使用一個或多個函式當作變數的函式)

將函式當作變數

在 Functional programming 中,function 可以被當作變數傳遞,

常見的情形如 Enum.map/2

匿名函式的情況

Enum.map([1, 2, 3], fn x -> x + 1 end)

普通函式,則是加上 & 並使用 / 標記上 arity

Enum.map(["one", "two", "three"], &String.upcase/1)
#=> ["ONE", "TWO", "THREE"]

常用的內建模組

除了可以省略模組的 Kernel 外 (其實 +, - 也是 Kernel 的函式)

我們寫應用的時候最常使用到的有下面幾個

List.first([1, 2, 3])
#=> 1
List.delete([:a, :b, :c], :d)
#=> [:a, :b, :c]

要注意的是,list 這個型別有 Enumerable protocol 所以可以使用 Enum 模組的函式
其實平常使用在 list 上的函式屬於 Enum 模組的情況還比較常見

Enum.count([1, 2, 3])
#=> 3
Enum.map([1, 2, 3], fn x -> x * 2 end)
#=> [2, 4, 6]
Enum.sort([3, 2, 1])
#=> [1, 2, 3]

在寫 Phoenix 應用的時候常常要處理 Map 與 Struct(之後介紹)

Map.get(%{name: "Jack", age: 3}, :name)
#=> "Jack"

Map.merge(%{a: 1, b: 2}, %{a: 3, d: 4})
#=> %{a: 3, b: 2, d: 4}

Map.keys(%{a: 1, b: 2})
[:a, :b]

收集了字串相關的方法,如

String.downcase("ABCD")
#=> "abcd"
String.replace("a,b,c", ",", "-")
#=> "a-b-c"

上一篇
2 快速上手夠用的 Elixir (IEX, 型別)
下一篇
4 快速上手夠用的 Elixir (Pattern matching)
系列文
Phoenix 1.7 完全教學30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言